/*
    The NeonX Library

    Copyright (c) 2013 darkcat

    Code covered by the MIT License
*/

#pragma once

//////////////////////////////////////////////////////////////////////////

#define NX_LOOP_0( ...)
#define NX_LOOP_1( f, i, e, nul, ite, ...)  NX_ARGS_(e(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), nul))
#define NX_LOOP_2( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_1( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_3( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_2( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_4( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_3( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_5( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_4( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_6( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_5( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_7( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_6( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_8( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_7( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_9( f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_8( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))

#define NX_LOOP_10(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_9( f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_11(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_10(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_12(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_11(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_13(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_12(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_14(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_13(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_15(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_14(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_16(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_15(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_17(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_16(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_18(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_17(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_19(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_18(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))

#define NX_LOOP_20(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_19(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_21(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_20(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_22(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_21(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_23(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_22(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_24(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_23(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_25(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_24(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_26(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_25(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_27(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_26(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_28(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_27(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_29(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_28(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))

#define NX_LOOP_30(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_29(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_31(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_30(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_32(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_31(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_33(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_32(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_34(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_33(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_35(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_34(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_36(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_35(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_37(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_36(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_38(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_37(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_39(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_38(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))

#define NX_LOOP_40(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_39(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_41(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_40(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_42(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_41(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_43(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_42(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_44(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_43(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_45(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_44(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_46(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_45(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_47(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_46(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_48(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_47(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
#define NX_LOOP_49(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_48(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))
                                                                                                                                    
#define NX_LOOP_50(f, i, e, nul, ite, ...)  NX_ARGS_(f(NX_ARGS_(__VA_ARGS__), NX_CONTER(ite), NX_LOOP_49(f, i, e, nul, NX_ARGS_(ite, -), i(NX_ARGS_(__VA_ARGS__)))))

/*
    Loop calls function

    NX_LOOP(4, f, i, e, nul, a, b, c)
    -->
    f(a, b, c, 1, \
        f(i(a, b, c), 2, \
            f(i(i(a, b, c)), 3, \
                e(i(i(i(a, b, c))), 4, nul) \
            ) \
        ) \
    )
*/

#define NX_LOOP_(n)                         NX_JOIN(NX_LOOP_, n)
#define NX_LOOP(n, f, i, e, nul, ...)       NX_PROXY(NX_LOOP_(n), f, i, e, nul, -, __VA_ARGS__)
#define NX_LOOP_MAX(f, i, e, nul, ...)      NX_LOOP(NX_MACRO_MAX, f, i, e, nul, __VA_ARGS__)
